﻿namespace Nello.Data
{
    using Nello;
    using System;
    using System.Data;
    using System.Data.Common;

    public class Linker : ILinker, IConnectionInfo
    {
        protected DbCommand cmd;
        private System.Data.CommandType cmdType;
        protected DbConnection cnn;
        protected string cnnStr;
        private System.Data.Common.DbProviderFactory factory;

        public Linker()
        {
            this.cnn = null;
            this.cmd = null;
            this.cnnStr = "";
            this.factory = ClassFactory.DbProviderFactory;
            this.cmdType = System.Data.CommandType.Text;
        }

        public Linker(string cnnStr)
        {
            this.cnn = null;
            this.cmd = null;
            this.cnnStr = "";
            this.factory = ClassFactory.DbProviderFactory;
            this.cmdType = System.Data.CommandType.Text;
            this.cnnStr = cnnStr;
        }

        public void AddParameter(string name, object value)
        {
            this.AddParameter(DbType.String, ParameterDirection.Input, name, value);
        }

        public void AddParameter(DbType dbtype, string name, object value)
        {
            this.AddParameter(dbtype, ParameterDirection.Input, name, value);
        }

        public void AddParameter(DbType dbtype, ParameterDirection direction, string name, object value)
        {
            IDataParameter p = this.cmd.CreateParameter();
            p.DbType = dbtype;
            p.Direction = direction;
            p.ParameterName = name;
            p.Value = value;
            this.cmd.Parameters.Add(p);
        }

        public void Close()
        {
            this.cmd.Dispose();
            if (this.cnn.State == ConnectionState.Open)
            {
                this.cnn.Close();
            }
        }

        public void Commit()
        {
            this.cmd.Transaction.Commit();
        }

        public DataRow ExecuteDataRow(string sql)
        {
            return this.ExecuteDataTable(sql).Rows[0];
        }

        public DataSet ExecuteDataSet(string sql)
        {
            this.cmd.CommandText = sql;
            DataSet ds = new DataSet();
            DbDataAdapter adp = this.DbProviderFactory.CreateDataAdapter();
            adp.SelectCommand = this.cmd;
            adp.Fill(ds);
            return ds;
        }

        public DataTable ExecuteDataTable(string sql)
        {
            this.cmd.CommandText = sql;
            DataTable dt = new DataTable();
            DbDataAdapter adp = this.DbProviderFactory.CreateDataAdapter();
            adp.SelectCommand = this.cmd;
            adp.Fill(dt);
            return dt;
        }

        private int ExecuteLog(string sql)
        {
            string sqlt = "INSERT INTO t_sys_log(fguid, ftext) VALUES('{0}', '{1}')";
            sqlt = string.Format(sqlt, Util.NewGuid(), sql.Replace('\'', '"'));
            this.cmd.CommandText = sqlt;
            return this.cmd.ExecuteNonQuery();
        }

        public int ExecuteNonQuery(string sql)
        {
            this.cmd.CommandText = sql;
            int ret = this.cmd.ExecuteNonQuery();
            if (!(sql.Trim().StartsWith("select", StringComparison.CurrentCultureIgnoreCase) || !(AppSettings.Get("EnableDPE") == "true")))
            {
                this.ExecuteLog(sql);
            }
            return ret;
        }

        public object ExecuteScalar(string sql)
        {
            this.cmd.CommandText = sql;
            return this.cmd.ExecuteScalar();
        }

        public void Open()
        {
            this.Open(true);
        }

        public void Open(bool beginTran)
        {
            this.cnn = this.DbProviderFactory.CreateConnection();
            this.cnn.ConnectionString = this.ConnectionString;
            this.cnn.Open();
            this.cmd = this.cnn.CreateCommand();
            this.cmd.CommandType = this.cmdType;
            if (beginTran)
            {
                this.cmd.Transaction = this.cnn.BeginTransaction();
            }
        }

        public void Rollback()
        {
            this.cmd.Transaction.Rollback();
        }

        public System.Data.CommandType CommandType
        {
            get
            {
                return this.cmdType;
            }
            set
            {
                this.cmdType = value;
            }
        }

        public string ConnectionString
        {
            get
            {
                if (this.cnnStr == "")
                {
                    return ClassFactory.ConnectionString;
                }
                return this.cnnStr;
            }
            set
            {
                this.cnnStr = value;
            }
        }

        public System.Data.Common.DbProviderFactory DbProviderFactory
        {
            get
            {
                return this.factory;
            }
            set
            {
                this.factory = value;
            }
        }
    }
}

